package main

import (
	"bytes"
	"context"
	"errors"
	"mangos/internal/crypto/srp6"
	"mangos/internal/math/big"
	"net"
	"strings"
	"sync"
	"time"
)

// conn 连接对象
type conn struct {
	rw       net.Conn     // 连接
	rb       bytes.Buffer // 输入缓存
	wb       bytes.Buffer // 输出缓存
	srp      srp6.Host    // SRP6主机端
	recProof *big.Int     // SRP6重连验证
	login    string       // SRP6用户名
}

// RemoteAddr 获取连接的远程地址
func (c *conn) RemoteAddr() net.Addr {
	return c.rw.RemoteAddr()
}

// ip 获取 IP 地址
func (c *conn) ip() string {
	addr := c.rw.RemoteAddr()
	return strings.Split(addr.String(), ":")[0]
}

// close 关闭连接
func (c *conn) close() {
	log("关闭客户端连接: %s", c.RemoteAddr())
	_ = c.rw.Close()
}

// sendByte 发送字节
func (c *conn) sendByte(b byte) error {
	return c.wb.WriteByte(b)
}

// send 发生字节序列
func (c *conn) send(buf []byte) (int, error) {
	return c.wb.Write(buf)
}

// run 连接数据处理
func (c *conn) run(waitGroup *sync.WaitGroup, context context.Context) {
	defer c.close()
	defer waitGroup.Done()

	for {
		select {
		case <-context.Done():
			return
		default:
			if !c.handleInput() || !c.handleOutput() {
				return
			}
		}
	}
}

// handleInput 处理输入
func (c *conn) handleInput() bool {
	// 设置接收超时时间
	err := c.rw.SetReadDeadline(time.Now().Add(time.Second * 5))
	if err != nil {
		logError("设置连接接收超时发生错误：%v", err)
		return false
	}

	// 接收数据
	n, err := c.rb.ReadFrom(c.rw)
	if err != nil {
		var opErr *net.OpError
		if errors.As(err, &opErr) && opErr.Timeout() {
			if n <= 0 {
				return true
			}
		} else {
			logError("接收数据出错: %s, %v", c.RemoteAddr(), err)
			return false
		}
	} else if n <= 0 {
		// 连接关闭
		return false
	}

	// 处理接收到的数据
	return c.handlePacket()
}

// handleOutput 处理输出
func (c *conn) handleOutput() bool {
	if c.wb.Len() > 0 {
		// 设置发送超时时间
		err := c.rw.SetWriteDeadline(time.Now().Add(time.Second * 5))
		if err != nil {
			logError("设置连接发送超时发生错误：%v", err)
			return false
		}

		// 发送数据
		n, err := c.wb.WriteTo(c.rw)
		if err != nil {
			var opErr *net.OpError
			if errors.As(err, &opErr) && opErr.Timeout() {
				if n <= 0 {
					return true
				}
			} else {
				logError("发送数据出错: %s, %v", c.RemoteAddr(), err)
				return false
			}
		}
		if n > 0 {
			c.wb.Truncate(c.wb.Len())
		}
	}

	return true
}

// handlePacket 处理数据包
func (c *conn) handlePacket() bool {
	req := c.rb.Bytes()
	cmd := req[0]
	// 查找命令处理程序
	handler, ok := commandHandlers[commandCode(cmd)]
	if !ok {
		logError("未知命令: %s, 0x%x", c.RemoteAddr(), cmd)
		return false
	}
	// 执行命令处理程序
	n := handler(c, req)
	if n == -1 {
		return false
	} else if n > 0 {
		c.rb.Next(int(n))
		c.rb.Truncate(c.rb.Len())
	}
	return true
}
